iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
1

寫在前面

最常跟Ruby一起聽到的名詞大概就是Rails了
Rails是Ruby的一個框架(開場白只是一個玩笑,別當真),目的在於加速Ruby的開發
不過這裡並不會直接從Rails教起,畢竟Rails的官方網站也說了,如果沒有Ruby的基本概念,那學習曲線將變得相當陡峭
所以我們今天從Ruby開始

早期的語言由於硬體等等方面的問題,都以機器的角度出發來設計程式語言
像是C++就需要提前告訴編譯器我們的程式有哪些,好讓他提前規劃空間
Java則是需要先編譯後再直譯,好讓語言可跨平台
而Ruby則是以人類的角度出發,讓人類覺得好寫是他的忠旨

準備好你的docker

讓我們進入Ruby的世界吧

在你的工作目錄建立一個convert.rb的檔案

def t2h(number)
    begin 
        num = number.to_i
        for i in 0...16
            for j in 0...16
                for k in 0...16
                    if  16**2*i+16**1*j+16**0*k == num
                        puts returnAE(i)+returnAE(j)+returnAE(k)
                    end
                end
            end
        end
    rescue 
        puts "wrong number"
    end
end

def returnAE(number)
    if number <10
        return number.to_s
    else
        case number
            when 10
                return "A"
            when 11
                return "B"
            when 12
                return "C"
            when 13
                return "D"
            when 14
                return "E"
            when 15
                return "F"
            else
                puts "Sonething wrong"
                return ""
        end
    end
end

def h2t(number)
    count = 0
    output = 0
    while count<number.length-1
        output += AEreturn(number[count])*16**(number.length-count-2)
        count += 1
    end       
    puts output
end

def AEreturn(number)
    case number
        when "A"
            num = 10
        when "B"
            num = 11
        when "C"
            num = 12
        when "D"
            num = 13
        when "E"
            num = 14
        when "F"
            num = 15
        else
            num = number.to_i
    end
    return num
end

loop do
    puts "Tell me what you want to"
    puts "(1)T to H (2)H to T"
    case gets.to_i
        when 1
            puts "Please enter the number:"
            number = gets
            t2h(number)
            
        when 2
            puts "Please enter the number:"
            number = gets
            h2t(number)
        else
            puts "Wrong selection"
    end
    puts ""
end

接著將資料夾掛載到docker並執行

docker container run --rm -it -v 你的工作資料夾:/home/ruby ruby:latest /bin/bash
root@21415376c8df:/# cd /home/ruby
root@21415376c8df:/home/ruby# ruby convert.rb

這下你的ruby程式就跑起來了,接下來我們講解語法

結構

Ruby是直譯式的語言,所以整體看起來會比較像python或是我們還沒介紹的Raku
程式進入點一樣在檔案的開頭,前面先定義方法,最後執行主程式

並且行尾都沒有;

輸入與輸出

先往下看到這段

loop do
    puts "Tell me what you want to"
    puts "(1)T to H (2)H to T"
    case gets.to_i
        when 1
            puts "Please enter the number:"
            number = gets
            t2h(number)
            
        when 2
            puts "Please enter the number:"
            number = gets
            h2t(number)
        else
            puts "Wrong selection"
    end
    puts ""
end

loop的用意在於讓你可以不斷的執行裡面的程式,直到遇到break
如果想要提前中止就使用ctrl+C
這樣我們就會一直在這隻程式當中,而不會只做完一次進位轉換就結束

輸出超級人性化

puts "Tell me what you want to"

完全沒有其他有的沒的
甚至連()都不需要,只要確保輸出的字串用""包起來即可

而輸入也是

case gets.to_i

gets就是等待使用者輸入,後面的to_i則是將輸入轉成整數
以往我們都要得到使用者輸入並丟入一個變數後才丟到switch做判斷
但是Ruby允許你減少一份工

case

case就是我們以前使用的switch
when則是我們以前使用的case

case gets.to_i
    when 1
        puts "Please enter the number:"
        number = gets
        t2h(number)
        
    when 2
        puts "Please enter the number:"
        number = gets
        h2t(number)
    else
        puts "Wrong selection"
end

注意不管是case是沒有{}的喔,相對的他使用end當作是case的結束(用意跟{}一樣表示範圍)
when也沒有:並且跟golang一樣when的結尾不需要break

在when裡面我們問使用者第二個問題,並且把拿到的使用者輸入丟入變數內

puts "Please enter the number:"
number = gets
t2h(number)

變數宣告是不需要var的,但是要用也是可以,並且還有@var跟$var表示變數種類的不同
取得變數後丟到t2h這個方法內做運算

方法宣告

往上看到t2h的方法宣告吧

def t2h(number)
    begin 
        num = number.to_i
        for i in 0...16
            for j in 0...16
                for k in 0...16
                    if  16**2*i+16**1*j+16**0*k == num
                        puts returnAE(i)+returnAE(j)+returnAE(k)
                    end
                end
            end
        end
    rescue 
        puts "wrong number"
    end
end

方法的關鍵字跟python一樣使用def
範圍則是使用end宣告而不是tab

另外由於ruby是動態型別(畢竟要讓人寫得舒服)輸入跟輸出都不需要宣告變數的型別

錯誤處理

注意到begin了嗎?

用途跟C#的try一樣,會嘗試執行裡面的程式碼,一旦報錯就會執行rescue裡面的程式
範圍一樣使用end宣告

型別系統

注意Ruby跟python一樣,雖然使用動態型別,但是他們都屬於強型別
因此我們必須先將輸入的字串轉型成整數型別

num = number.to_i

反過來將整數轉型成字串的作法如下

if number <10
    return number.to_s
else

相較於其他語言,ruby的轉型都很簡單而且統一

迴圈

剛才我們介紹過其中一種迴圈了,現在是我們以前用過的for迴圈

for i in 0...16

相較其他語言,ruby的宣告方式很特別
0...16表示迴圈會從0~15,總共16次

而0..16則表示會從0~16,總共17次

另外一種寫法是

10.times do |i|
    puts i
end

||裡面放著次數的宣告
這樣他就會循環10次

irb

如果你想要試玩程式碼,可以使用irb
試試看進入Ruby的docker後不執行Ruby而是打上irb
應該會出現

[Ruby]# docker container run --rm -it -v $PWD:/home/ruby ruby:latest /bin/sh
# irb        
irb(main):001:0>   //出現這行代表已經進入互動模式

這樣你就可以開始打程式碼了
像這樣

root@fbb632c84742:/# irb
irb(main):001:1* 10.times do |i|
irb(main):002:1*   puts i
irb(main):003:0> end

冪次

接下來我們來看看Ruby是怎麼計算冪次的

if  16**2*i+16**1*j+16**0*k == num

使用**就可以計算次方了
因此不用像其他語言需要import pow

字串

好,來看h2t(number)
裡面有一個有趣的現象

while count<number.length-1

while結構跟if類似,也是用end結尾,因此我們不詳細介紹
要注意的是這裡的number.length-1
在其他語言的寫法,這裡我們都不需要-1
而Ruby需要的原因是因為使用gets拿到的輸入會有換行符號
因此如果輸入是"FFF"長度實際上取出來會是4

你可以在irb試試看下面的程式

irb(main):001:0> gets 
FFF
=> "FFF\n"
irb(main):002:0> puts gets.length
FFF
4
=> nil
irb(main):003:0> puts "FFF".length
3
=> nil

看到第一個回傳值"FFF\n"最後面的\n就是換行符號
因此由於換行符號的關係,我們可以將取出的長度-1

這裡比較好的作法是chomp

irb(main):001:0> input = gets
FFF
irb(main):002:0> puts input.length
4
=> nil
irb(main):003:0> puts input.chomp.length
3
=> nil

先將輸入值放到input這個變數裡面接著看他的長度為4
chomp後就是3

破壞性執行

這裡有個有趣的東西是!
在ruby裡面!代表破壞性的執行,剛才沒有!的chomp實際上並沒有減去字串後面的換行符號
只有在輸出的當下有減去
如果要真正刪除後面的換行符號可以使用!chomp
試試看下面的程式碼吧

irb(main):001:0> input = gets
FFF
irb(main):002:0> puts input.length
4  //原本的長度為4
=> nil
irb(main):003:0> puts input.chomp.length
3  //這裡只有暫時性刪除換行長度為3
=> nil
irb(main):004:0> puts input.length
4 //因此在這裡再次確認長度時還是原本的4
=> nil
irb(main):005:0> puts input.chomp!.length
3 //這時使用chomp!來破壞性執行
=> nil
irb(main):006:0> puts input.length
3 //之後再次確認input的長度就是3了
=> nil

算是一個蠻有趣的關鍵字

以上就是Ruby的基本語法拉

我們來複習一下

  • 基本結構
    • 跟python一樣直譯式語言,從程式碼第一行開始執行
  • 印出/讀取
    • 使用puts跟gets
  • 方法的結構
    • 動態型別,不必提前命名回傳值的型別
    • 不使用{}而是使用end來宣告方法的範圍
  • 邏輯控制
    • case 就是以往的switch,同樣使用end做範圍宣告
    • if 不需要()跟{},使用end做範圍宣告
  • 迴圈控制
    • for 有著特殊的0...16,使用end做範圍宣告
    • while 使用end做範圍宣告
  • 型別
    • 跟python一樣屬於動態+強型別
  • 冪次計算 使用**而不使用一般的pow

Ruby寫起來比起其他語言輕鬆很多,
算是把其他語言貼近人類語言的寫法都整合了進來,統一的轉型風格,行尾不需要;
也不需要像python一樣擔心tab數量對不對,when的最後不需要break
算是很能體會到作者當初設計這門語言的用心

如果你喜歡這門語言,記得按贊分享加訂閱,可以去體會一下Rails
這裡分享一下使用docker建立Ruby on Rails的環境的方法
由於Rails幫你整合了很多東西,因此你必須原本就對網站的架構很熟悉才能體會到Rails的完整性

明天我們來介紹Raku(perl6),這門也是寫法舒適的語言
Ruby作者也說過啟發Ruby的語言是perl而不是python,連結


上一篇
php 長相如同半獸人般奇怪,曾經統治中土(網路)的王者
下一篇
Raku 簡單的事情應該保持簡單,複雜的事情應該讓它變得簡單,不可能的事情應該讓他變得可能
系列文
你會十五種程式語言?不,我會十五種HelloWorld.為了避免這種狀況,因此寫了這篇:淺入淺出十五種程式語言30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
skycover
iT邦新手 4 級 ‧ 2020-09-17 21:08:09

如果有任何寫不清楚或是觀念沒有很明白的話請留言告知我
會盡快補上

如果有任何寫錯的地方也麻煩留言告知我
會盡快修正

感謝各位

我要留言

立即登入留言